//
//  Directory.hpp
//  Simplels
//
//  Created by 陈新唯 on 16/4/16.
//  Copyright © 2016年 陈新唯. All rights reserved.
//

#ifndef Directory_hpp
#define Directory_hpp

#include <dirent.h>
#include <string>
#include "Unix.h"

namespace File {
    std::string getCWD();
	std::string getHomeDir();
	
	class Directory;
	// exception
	using DirectoryError = Unix::SysError<Directory>;

	// this micro is used to prohibit copy and move operations of Directory
#define DIRECTORY_NOCOPY
	class Directory {
	public:
		// default constructor don't open any File
		Directory() {}
		
		explicit Directory(const std::string &s);
		explicit Directory(std::string &&s);
		
		// i'm doubt whether copy and move operations is needed
		// for practice, i implement these operations
		// doing so i have to add an additional data member copies
		Directory(const Directory &rhs)
#ifdef DIRECTORY_NOCOPY
		= delete
#endif
		;
		Directory& operator=(const Directory &rhs)
#ifdef DIRECTORY_NOCOPY
		= delete
#endif
		;
		
		Directory(Directory &&rhs)
#ifdef DIRECTORY_NOCOPY
		= delete
#endif
		;
		Directory& operator=(Directory &&rhs)
#ifdef DIRECTORY_NOCOPY
		= delete
#endif
		;
		
		~Directory();
		
		DIR *getDirectory() const { return dir; }
		void setDirectory(const std::string &s);
		void setDirectory(std::string &&s);
		
		dirent *getEntry() const { return readdir(dir); }
		void listFiles() const;
	private:
		void initCopies();
		void destroy();
		
		DIR *dir = nullptr;
		// data member copies is needed because of copy and move operations
		// so if these operations are declared = delete, there is no need of copies
#ifndef DIRECTORY_NOCOPY
		int *copies = nullptr;
#endif
	};
	
	inline std::string path(std::string &&s) {
		if (s.empty())
			return getHomeDir();
		if (s[0] == '~')
			return getHomeDir() + (s.data() + 1);
		return std::move(s);
	}
}


#endif /* Directory_hpp */